package com.freecloud.javabasics.design.proxy.custom.core;

import javax.tools.JavaCompiler;
import javax.tools.StandardJavaFileManager;
import javax.tools.ToolProvider;
import java.io.File;
import java.io.FileWriter;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;

/**
 * @Author: maomao
 * @Date: 2020-03-01 21:19
 */
public class FreeProxy {

    public static final String ln = "\r\n";

    public static Object newProxyInstance(ClassLoader loader,
                                          Class<?>[] interfaces,
                                          FreeInvocationHandler h){
        //1. 动态生成源码.java文件

        String src = generateSrc(interfaces);

        System.out.println(src);

        //2. Java文件输出到磁盘

        try {
            String filePath = FreeProxy.class.getResource("").getPath();
            File f = new File(filePath + "$Proxy0.java");
            FileWriter fw = null;
            fw = new FileWriter(f);
            fw.write(src);
            fw.flush();
            fw.close();

            //3. 编译Java文件成.class
            JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
            StandardJavaFileManager manager = compiler.getStandardFileManager(null,null,null);

            Iterable iterable = manager.getJavaFileObjects(f);

            JavaCompiler.CompilationTask task = compiler.getTask(null,manager,null,null,null,iterable);

            task.call();
            manager.close();


            //4. 生成的.class加载到JVM中

            Class proxyClass = loader.loadClass("$Proxy0");

            Constructor c = proxyClass.getConstructor(FreeInvocationHandler.class);

            //5. 反回新的代理对象
            return c.newInstance(h);
        } catch (Exception e) {
            e.printStackTrace();
        }



        return null;
    }

    private static String generateSrc(Class<?>[] interfaces) {

        StringBuilder sb = new StringBuilder();
        sb.append("package com.freecloud.javabasics.design.proxy.custom.core;" + ln);
        //导入包
        sb.append("import java.lang.reflect.*;" + ln);

        sb.append("public final class $Proxy0 implements " + interfaces[0].getName() + " { " + ln);
        sb.append("FreeInvocationHandler h;" + ln);
        sb.append("public $Proxy0(FreeInvocationHandler h) {" + ln);
        sb.append("this.h = h;" + ln);
        sb.append("}" + ln);

        for (Method m : interfaces[0].getMethods()){
            Class<?>[] params = m.getParameterTypes();


            //添加方法参数
//            StringBuilder paramNames = new StringBuilder();
//            StringBuilder paramValues = new StringBuilder();
//            StringBuilder paramClass = new StringBuilder();
//
//            for (int i = 0;i < params.length;i++){
//                Class clazz = params[i];
//            }

            sb.append("public " + m.getReturnType().getName() + " " + m.getName() + "() {" + ln);
                sb.append("try{" + ln);

                sb.append("Method m = " + interfaces[0].getName() + ".class.getMethod(\"" + m.getName() + "\" ,new Class[]{});" + ln);
                sb.append("this.h.invoke(this,m,new Object[]{});" + ln);
                sb.append("return;"+ ln);

                sb.append("} catch(Exception e) {"+ ln);
                sb.append(" e.printStackTrace();" + ln);
                sb.append("}" + ln);

                sb.append("catch (Throwable throwable) {\n" +
                        "                throwable.printStackTrace();\n" +
                        "}" + ln);



            sb.append("}");
        }


        sb.append("}");

        return sb.toString();
    }
}
